package org.jeecg.modules.demo.ysd.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthWechatMiniProgramRequest;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.shiro.ShiroConfig;
import org.jeecg.modules.demo.ysd.entity.YsdSleepLog;
import org.jeecg.modules.demo.ysd.entity.YsdSleepLogScore;
import org.jeecg.modules.demo.ysd.entity.YsdUserInfo;
import org.jeecg.modules.demo.ysd.service.IYsdSleepLogScoreService;
import org.jeecg.modules.demo.ysd.service.IYsdSleepLogService;
import org.jeecg.modules.demo.ysd.service.IYsdUserInfoService;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

@Tag(name = "就医地图")
@RestController
@RequestMapping("/ysd")
@Slf4j
public class WeiXinLoginController {

    public static String appId = "wx9100c94d8e7888d7";

    @Autowired
    ISysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ShiroConfig shiroConfig;
    @Autowired
    private IYsdUserInfoService ysdUserInfoService;
    @Autowired
    private IYsdSleepLogService sleepLogService;
    @Autowired
    private IYsdSleepLogScoreService sleepLogScoreService;

    @PostMapping(value = "/sleepLogScore/list")
    public Result<List<YsdSleepLogScore>> sleepLogScoreList() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<YsdSleepLogScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YsdSleepLogScore::getUserId, loginUser.getId());
        List<YsdSleepLogScore> list = sleepLogScoreService.list(wrapper);
        Result<List<YsdSleepLogScore>> result = Result.ok();
        result.setResult(list);


        return result;
    }

    @PostMapping(value = "/sleepLogScore/count")
    public Result<Integer> sleepLogScore() {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<YsdSleepLogScore> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YsdSleepLogScore::getUserId, loginUser.getId());

        AtomicInteger score = new AtomicInteger();
        List<YsdSleepLogScore> list = sleepLogScoreService.list(wrapper);
        list.forEach(item -> {
            score.addAndGet(Integer.parseInt(item.getScore()));
        });
        Result<Integer> result = Result.ok();
        result.setResult(score.get());
        return result;
    }

    @PostMapping(value = "/sleepLog/save")
    public Result<Boolean> getSleepLogSave(@RequestBody List<YsdSleepLog> sleepLog) throws ParseException {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<YsdSleepLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YsdSleepLog::getUserId, loginUser.getId());
        wrapper.eq(YsdSleepLog::getRecordDate, sleepLog.get(0).getRecordDate());
        sleepLogService.remove(wrapper);

        sleepLog.forEach(item -> {
            item.setUserId(loginUser.getId());
        });

        sleepLogService.saveOrUpdateBatch(sleepLog);

        LambdaQueryWrapper<YsdSleepLogScore> wrapperScore = new LambdaQueryWrapper<>();
        wrapperScore.eq(YsdSleepLogScore::getUserId, loginUser.getId());
        wrapperScore.eq(YsdSleepLogScore::getRecordDate, sleepLog.get(0).getRecordDate());
        long size = sleepLogScoreService.count(wrapperScore);
        if (size == 0){
            YsdSleepLogScore ysdSleepLogScore = new YsdSleepLogScore();
            ysdSleepLogScore.setUserId(loginUser.getId());

            boolean notToday = isNotToday(sleepLog.get(0).getRecordDate());
            ysdSleepLogScore.setScore(notToday ? "1" : "2");
            ysdSleepLogScore.setType(notToday ? "1" : "2");
            ysdSleepLogScore.setRecordDate(sleepLog.get(0).getRecordDate());
            sleepLogScoreService.save(ysdSleepLogScore);
        }
        return Result.ok();
    }

    public boolean isNotToday(String dateString) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        Date dateToCheck = formatter.parse(dateString);
        // 将Date转换为LocalDate
        LocalDate inputDate = dateToCheck.toInstant()
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 比较是否不等于今天
        return !inputDate.isEqual(today);
    }

    @PostMapping(value = "/sleepLog/status")
    public Result<Boolean> getSleepLogStatus(@RequestBody String date) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryWrapper<YsdSleepLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(YsdSleepLog::getUserId, loginUser.getId());
        wrapper.eq(YsdSleepLog::getRecordDate, date);
        long size = sleepLogService.count(wrapper);
        Result<Boolean> result = new Result<>();
        result.setResult(size > 0);
        return result;
    }

    @PostMapping(value = "/getUserInfo")
    public Result<UserInfoReq> saveUserInfo() {
        LoginUser loginUser1 = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        SysUser loginUser = sysUserService.getById(loginUser1.getId());
        YsdUserInfo ysdUserInfo = ysdUserInfoService.getById(loginUser.getId());

        UserInfoReq userInfoReq = new UserInfoReq();
        userInfoReq.setName(ysdUserInfo.getUsername());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        userInfoReq.setBirth(sdf.format(loginUser.getBirthday()));
        userInfoReq.setRealName(loginUser.getRealname());
        userInfoReq.setGender(loginUser.getSex().toString());
        userInfoReq.setPhoneNumber(loginUser.getPhone());
        userInfoReq.setHospital(ysdUserInfo.getHospital());
        userInfoReq.setAddress(JSONObject.parseArray(ysdUserInfo.getProvince(), String.class));

        Result<UserInfoReq> userInfoReqResult = Result.ok();
        userInfoReqResult.setResult(userInfoReq);
        return userInfoReqResult;

    }


    @PostMapping(value = "/saveUserInfo")
    public Result<String> saveUserInfo(@RequestBody UserInfoReq userInfoReq) {

        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        log.info(JSONObject.toJSONString(loginUser));

        SysUser sysUserCheck = sysUserService.getUserByName(userInfoReq.name);
        if (Objects.nonNull(sysUserCheck) && !sysUserCheck.getId().equals(loginUser.getId())){
            return Result.error("用户名已被占用");
        }

        SysUser sysUser = sysUserService.getById(loginUser.getId());
        sysUser.setRealname(userInfoReq.realName);
//        sysUser.setUsername(userInfoReq.name);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // Explicitly set timezone if needed
        try {
            Date date = sdf.parse(userInfoReq.birth);
            sysUser.setBirthday(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        sysUser.setPhone(userInfoReq.getPhoneNumber());
        sysUser.setSex(Integer.valueOf(userInfoReq.getGender()));
        sysUserService.updateById(sysUser);

        YsdUserInfo ysdUserInfo = new YsdUserInfo();
        ysdUserInfo.setId(sysUser.getId());
        ysdUserInfo.setHospital(userInfoReq.getHospital());
        ysdUserInfo.setProvince(JSONObject.toJSONString(userInfoReq.address));
        ysdUserInfo.setUsername(userInfoReq.name);
        ysdUserInfoService.saveOrUpdate(ysdUserInfo);

        return Result.ok();
    }

    @PostMapping(value = "/login/auth/callback")
    public Result<String> callback(@RequestBody AuthCallback callback) {
        log.info(JSONObject.toJSONString(callback));
        return Result.ok();
    }

    @PostMapping(value = "/decode-phone")
    public Result<JSONObject> decodePhone(@RequestBody LoginReq req) {
        log.info(JSONObject.toJSONString(req));

        AuthWechatMiniProgramRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder()
                .clientId(appId)
                .clientSecret("00ab88c3fcc34e6968283bfa58eda1ba")
                .ignoreCheckRedirectUri(true)
                .ignoreCheckState(true)
                .build());

        AuthCallback callback = AuthCallback.builder()
                .code(req.code)
                .build();
        AuthResponse<AuthUser> response = authRequest.login(callback);

        if (response.ok()) {
            AuthUser authUser = response.getData();
            log.info(JSONObject.toJSONString(authUser));
        }
        return Result.ok();
    }

    @PostMapping(value = "/login")
    public Result<JSONObject> add(@RequestBody LoginReq req) {

        log.info(JSONObject.toJSONString(req));

        AuthWechatMiniProgramRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder()
                .clientId(appId)
                .clientSecret("00ab88c3fcc34e6968283bfa58eda1ba")
                .ignoreCheckRedirectUri(true)
                .ignoreCheckState(true)
                .build());

        AuthCallback callback = AuthCallback.builder()
                .code(req.code)
                .build();
        AuthResponse<AuthUser> response = authRequest.login(callback);

        if (response.ok()) {
            AuthUser authUser = response.getData();
            log.info(JSONObject.toJSONString(authUser));


            String openid = authUser.getUuid();

            LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysUser::getThirdId, openid);
            SysUser sysUser = sysUserService.getOne(queryWrapper);
            if (Objects.isNull(sysUser)){
                SysUser sysUserSave = new SysUser();
//                String username = "123";
                sysUserSave.setThirdId(openid);
//                sysUserSave.setUsername(openid);
                sysUserSave.setUsername(openid);
                sysUserSave.setDelFlag(0);
                sysUserSave.setStatus(1);
                String salt = oConvertUtils.randomGen(8);
                sysUserSave.setSalt(salt);
                String passwordEncode = PasswordUtil.encrypt(openid, openid, salt);
                sysUserSave.setPassword(passwordEncode);
                sysUserService.save(sysUserSave);
                sysUser = sysUserService.getOne(queryWrapper);
            }

            String token = JwtUtil.sign(openid, openid);
            JSONObject jsonObject = new JSONObject();
            redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
            redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 4 / 1000);
            jsonObject.put("token", token);
            jsonObject.put("thirdId", openid);
            jsonObject.put("userInfo", sysUser);

            Result<JSONObject> result = new Result<JSONObject>();

            result.setResult(jsonObject);

            return result;
        }

        return Result.OK("OK！");
    }





}
